package ain;

import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import util.CustomFormatter;

import environment.Ball;
import environment.Pitch;
import environment.player.Player;

public class ImmuneNetwork
{
	private ArrayList<? extends Antibody> antibodies;
	
	// 0. Shoot
	// 1. Pass - not used
	// 2. Kick
	// 3. Chase
	// 4. Track
	// 5. Guard
	private static double[][] antibodyAffinityValues = {	{ 1.0,  0.5, -0,8, -0.5,  0.5, -0.8},
								{ 0.2,  1.0,  0.2, -0.2,  0.5, -0.5},
								{-0.8,  0.0,  1.0,  0.5,  0.5,  0.2},
								{-0.5,  0.0, -0.5,  1.0,  0.0,  0.0},
								{-0.5, -0.5, -0.5, -0.2,  1.0, -0.5},
								{-0.8,  0.0,  0.2,  0.2, -0.2,  1.0}};
	
//	private static double[][] antibodyAffinityValues = {	{ 1.0,  0.5,  0,8,  0.5,  0.5,  0.8},
//								{ 0.2,  1.0,  0.2, -0.2,  0.5, -0.5},
//								{ 0.8,  0.0,  1.0,  0.5,  0.5,  0.2},
//								{ 0.5,  0.0,  0.5,  1.0,  0.0,  0.0},
//								{ 0.5,  0.5,  0.5,  0.2,  1.0,  0.5},
//								{ 0.8,  0.0,  0.2,  0.2,  0.2,  1.0}};
	
	private static double naturalDeathCoefficient = 0.2; // arbitrary
	
	public ImmuneNetwork(ArrayList<? extends Antibody> antibodies)
	{		
		this.antibodies = antibodies;
	}
	
	public void update()
	{
		// 1. calculate affinity with antigens
		// 2. calculate antibody concentrations
		
		// calculate affinity with antigens
		for (Antibody a : antibodies)
		{
			// preparation: update concentration change value such that 
			// it is calculated with the previous concentration
			a.concentrationChange();
			
			// 1.
			a.antigenAffinity();
			// 2.
			antibodyConcentration();
		}
	}
	
	private void antibodyConcentration()
	{
		for (Antibody a : antibodies)
		{			
			int id = a.getID();
			
			// calculate stimulating and suppressing network effect
			double stimulation = 0;
			double suppression = 0;
			for (Antibody b : antibodies)
			{
//				stimulation += antibodyAffinityValues[id][b.getID()] * b.getConcentration();
//				suppression += antibodyAffinityValues[b.getID()][id] * b.getConcentration();
				stimulation += antibodyAffinityValues[b.getID()][id] * b.getConcentration();
				stimulation += antibodyAffinityValues[id][b.getID()] * b.getConcentration();
			}
			
			// bringing it all together: (stim - suppr + antigenAff - deathCoeff) * oldConcentr
			double result = (stimulation - suppression 
					+ a.getAntigenAffinity() - naturalDeathCoefficient) * a.getConcentration();
			
			a.setConcentrationChange(result);
			
//			System.out.println(a.toString() + " " + a.getConcentration() + " " + result);
		}
	}
	
	public String toString()
	{
		return "" + antibodies.size();
	}
	
	public ArrayList<? extends Antibody> getAntibodies()
	{
		return antibodies;
	}
}
